//
//  GaKeyChainModel.m
//  DeviceId
//
//  Created by GikkiAres on 2020/4/4.
//  Copyright © 2020 TinyWind. All rights reserved.
//

#import "JsKeyChainManagerA.h"

@implementation JsKeyChainManagerA

+ (instancetype)sharedInstance {
	static JsKeyChainManagerA * _sharedInstance;
	static dispatch_once_t onceToken;
	dispatch_once(&onceToken, ^{
		_sharedInstance = [[JsKeyChainManagerA alloc]init];
	});
	return _sharedInstance;
}

#pragma mark Interface
- (BOOL)saveString:(NSString *)string forKey:(NSString *)key {
	JsKeyChainItemA * item = [[JsKeyChainItemA alloc]initWithString:string servie:key accessGroup:nil];
	return [self.class saveItemToKeyChain:item];
}

- (NSString *)stringForKey:(NSString *)key {
	JsKeyChainItemA * item = [[self.class queryAllKeyChainItemWithService:key accessGroup:nil] firstObject];
	return item.stringData;
}


+ (BOOL)saveItemToKeyChain:(JsKeyChainItemA *)item {
        //添加查询字典
        NSMutableDictionary * mdic =[@{
            //指定项目要保存的内容.
            (NSString *)kSecValueData:item.data
            //指定项目的类型
            ,(NSString *)kSecClass:(NSString *)kSecClassGenericPassword
        } mutableCopy];
        if(item.service) {
            mdic[(NSString *)kSecAttrService] = item.service;
        }
        if(item.accessGroup) {
            mdic[(NSString *)kSecAttrAccessGroup] = item.accessGroup;
        }
        
        //如果有,就更新,没有就新增.
        OSStatus status = SecItemAdd((CFDictionaryRef)mdic, nil);
        if(status == errSecSuccess) {
            NSLog(@"保存数据到KeyChain成功:%@",[item stringData]);
            return YES;
        }
        else {

            NSString * errorInfo = [self.class detailForStatus:status];
            NSLog(@"保存数据到KeyChain,失败,原因为:%@",errorInfo);

            return NO;
        }
}

+ (NSString *)detailForStatus:(OSStatus)status {
    NSString * errInfo;
    if (@available(iOS 11.3, *)) {
        errInfo = (NSString *)CFBridgingRelease(SecCopyErrorMessageString(status, nil));
    } else {
        // Fallback on earlier versions
         errInfo = @(status).description;
    }
    return errInfo;
}


/**
 将uddateQuery中的数据,更新到item中.
 item的value和data重复了?
 */
- (BOOL)updateValue:(JsKeyChainItemA *)item {
        //创建搜索查询字典
       NSMutableDictionary * searchQuery =[NSMutableDictionary dictionary];
            //指定项目的类型
        searchQuery[(NSString *)kSecClass]=(NSString *)kSecClassGenericPassword;
        if(item.service) {
            searchQuery[(NSString *)kSecAttrService] = item.service;
        }
        if(item.accessGroup) {
            searchQuery[(NSString *)kSecAttrAccessGroup] = item.accessGroup;
        }
    
    //创建更新查询字典
        NSMutableDictionary * updateQuery =[NSMutableDictionary dictionary];
            //指定项目的类型
        updateQuery[(NSString *)kSecValueData]=item.data;
        
        OSStatus status = SecItemUpdate((CFDictionaryRef)searchQuery, (CFDictionaryRef)updateQuery);
        if(status == errSecSuccess) {
            NSLog(@"更新数据到KeyChain,成功,数据为:%@",item.data);
            return YES;
        }
        else {
            NSString * errorInfo = [self.class detailForStatus:status];
            NSLog(@"更新数据到KeyChain,失败,原因为:%@",errorInfo);
            return NO;
        }
}



- (BOOL)removeFormKeyChain:(JsKeyChainItemA *)item {
    //创建删除查询字典

    NSMutableDictionary * mdic =[NSMutableDictionary dictionary];
        //指定项目的类型
    mdic[(NSString *)kSecClass]=(NSString *)kSecClassGenericPassword;
    if(item.service) {
        mdic[(NSString *)kSecAttrService] = item.service;
    }
    if(item.accessGroup) {
        mdic[(NSString *)kSecAttrAccessGroup] = item.accessGroup;
    }
    
       OSStatus status = SecItemDelete((CFDictionaryRef)mdic);
           if(status == errSecSuccess) {
               NSLog(@"KeyChain删除数据,成功,service为%@",item.service);
               return YES;
           }
           else if(status == errSecItemNotFound) {
               NSLog(@"KeyChain删除数据,成功,没有匹配的钥匙链项目.");
           }
           else {
               NSString * errorInfo = [self.class detailForStatus:status];
               NSLog(@"KeyChain删除数据,失败,原因为:%@",errorInfo);
           }
    return NO;
}

+ (NSArray <JsKeyChainItemA *>*)queryAllKeyChainItem {
   return  [self queryAllKeyChainItemWithService:nil accessGroup:nil];
}

+ (NSArray<JsKeyChainItemA *> *)queryAllKeyChainItemWithService:(NSString *)service {
    return  [self queryAllKeyChainItemWithService:service accessGroup:nil];
}


+ (NSArray<JsKeyChainItemA *> *)queryAllKeyChainItemWithService:(NSString *_Nullable)service accessGroup:(NSString *_Nullable)accessGroup {
    NSMutableArray * marrResult = [NSMutableArray array];
    //搜索查询字典
    NSMutableDictionary * searchQuery =[self searchQueryDictionaryForService:service accessGroup:accessGroup isSingleMatch:NO isReturnData:YES isReturnAttributes:YES];

    CFTypeRef result = nil;
    OSStatus status = SecItemCopyMatching((CFDictionaryRef)searchQuery, (CFTypeRef *)&result);
        if(status == errSecSuccess) {
            //指定的是返回多个结果,所以结果是数组.
            NSArray * arrResult = (__bridge NSArray *)result;
            [arrResult enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                NSDictionary * dic = obj;
				JsKeyChainItemA * item = [[JsKeyChainItemA alloc]initWithDictionary:dic];
//                NSLog(@"item is %@",dic);
                [marrResult addObject:item];
               
            }];
//            NSLog(@"KeyChain查询数据,成功,一个有%zi个项目",marrResult.count);
        }
        else if(status == errSecItemNotFound) {
            NSLog(@"KeyChain查询数据,成功,没有匹配的钥匙链项目.");
        }
        else {
           NSString * errorInfo = [self detailForStatus:status];
            NSLog(@"KeyChain查询数据,失败,原因为:%@",errorInfo);
        }
    return marrResult;
}


//searchQuery的字典
+ (NSMutableDictionary *)searchQueryDictionaryForService:(NSString *)service accessGroup:(NSString * _Nullable)accessGroup isSingleMatch:(BOOL)isSingleMatch isReturnData:(BOOL)isReturnData isReturnAttributes:(BOOL)isReturnAttributes{
    NSMutableDictionary * searchQuery =[NSMutableDictionary dictionary];
    //指定项目的类型,必填项.
    searchQuery[(NSString *)kSecClass]=(NSString *)kSecClassGenericPassword;

    //返回的结果数量
    if(isSingleMatch) {
        searchQuery[(NSString *)kSecMatchLimit]=(NSString *)kSecMatchLimitOne;
    }
    else {
        searchQuery[(NSString *)kSecMatchLimit]=(NSString *)kSecMatchLimitAll;
    }
    
    //是否返回项目的数据
    if(isReturnData) {
        
        searchQuery[(NSString *)kSecReturnData]=(id)kCFBooleanTrue;
    }
    else {
        searchQuery[(NSString *)kSecReturnData]=(id)kCFBooleanFalse;
    }
    
    //是否返回项目属性
    if(isReturnAttributes) {
        searchQuery[(NSString *)kSecReturnAttributes]=(id)kCFBooleanTrue;
    }
    else {
        searchQuery[(NSString *)kSecReturnAttributes]=(id)kCFBooleanFalse;
    }
    
    if(service) {
        searchQuery[(NSString *)kSecAttrService] = service;
    }
      if(accessGroup) {
          searchQuery[(NSString *)kSecAttrAccessGroup] = accessGroup;
      }
    
    return searchQuery;
}




@end
